#pragma once
#include "Heap.h"
#include "snake.h"

// 堆相关函数（保留原有代码）
//初始化
void HeapInit(hp* php)
{
	assert(php != nullptr);

	//初始化4空间
	php->arr = (DataType*)malloc(sizeof(DataType) * 4);

	if (php->arr == nullptr)
	{
		perror("malloc fail");
		return;
	}

	//实际存储个数
	php->size = 0;

	//可存储最大个数
	php->capacity = 4;
}

//向上调整
void UpAdjust(DataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			std::swap(a[child], a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else break;
	}
}

//插入数据[向上调整]
void HeapPush(hp* php, DataType x)
{
	assert(php != nullptr);

	//扩容
	if (php->size == php->capacity)
	{
		DataType* tmp = (DataType*)realloc(php->arr, sizeof(DataType) * php->capacity * 2);
		if (tmp == nullptr)
		{
			perror("realloc fail");
			return;
		}
		php->arr = tmp;
		//成功扩容后更新容量
		php->capacity *= 2;
	}
	php->arr[php->size++] = x;

	UpAdjust(php->arr, php->size - 1);
}

//向下调整
void DownAdjust(DataType* a, int n, int parent)
{
	//找最小孩子
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] < a[child])
			++child;

		if (a[child] < a[parent])
		{
			std::swap(a[parent], a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else break;
	}
}

//删除堆顶元素
void HeapPop(hp* php)
{
	assert(php != nullptr);
	assert(!HeapEmpty(php));
	std::swap(php->arr[0], php->arr[php->size - 1]);
	(php->size)--;
	DownAdjust(php->arr, php->size, 0);
}

//取堆顶元素
DataType HeapTop(hp* php)
{
	assert(php != nullptr);
	return php->arr[0];
}
//堆是否为空
bool HeapEmpty(hp* php)
{
	assert(php != nullptr);
	return php->size == 0;
}
//元素个数
int HeapSize(hp* php)
{
	assert(php != nullptr);
	return php->size;
}

//销毁堆
void HeapDestory(hp* php)
{
	assert(php != nullptr);
	free(php->arr);
	php->arr = nullptr;
	php->capacity = php->size = 0;
}

// 贪吃蛇游戏相关函数实现

// 设置光标位置
void SetPos(short x, short y)
{
	// 获取标准输出流的句柄
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);

	// 想设置光标的坐标
	COORD pos = { x, y };
	SetConsoleCursorPosition(handle, pos);
}

// 欢迎界面
void WelcomeUser()
{
	SetPos(46, 12);
	wprintf(L"欢迎来到贪吃蛇小游戏：");
	SetPos(48, 17);
	system("pause");
	system("cls");

	SetPos(40, 10);
	wprintf(L"用↑ ↓ ← →来控制蛇移动的方向，F3加速， F4减速\n");

	SetPos(40, 15);
	wprintf(L"加速可以获得更高的分数\n");

	SetPos(40, 20);
	system("pause");
	system("cls");
}

// 绘制地图
void CreatMap()
{
	// 幕布大小：58 * 27
	// 但由于一个方框是宽字符，占两个字节大小位置，所以行循环29次即可，列（27 - 2）次

	// 上
	for (int i = 0; i < 57; i++)
		wprintf(L"%lc", L'□');

	// 下
	SetPos(0, 26);
	for (int i = 0; i < 57; i++)
		wprintf(L"%lc", L'□');

	// 左
	for (int i = 1; i <= 25; i++)
	{
		SetPos(0, i);
		wprintf(L"%lc", L'□');
	}

	// 右
	for (int i = 1; i <= 25; i++)
	{
		SetPos(56, i);
		wprintf(L"%lc", L'□');
	}
}

// 初始化蛇
void InitSnake(Snake* snake)
{
	snake->head = (SnakeNode*)malloc(sizeof(SnakeNode));
	snake->tail = snake->head;
	snake->length = 1;
	snake->direction = RIGHT;
	
	// 蛇初始位置在中间
	snake->head->pos.x = WIDTH / 2;
	snake->head->pos.y = HEIGHT / 2;
	snake->head->next = NULL;
}

// 初始化食物
void InitFood(Food* food)
{
	food->pos.x = rand() % (WIDTH - 2) + 1;
	food->pos.y = rand() % (HEIGHT - 2) + 1;
	food->type = 1; // 普通食物
}

// 绘制蛇
void DrawSnake(Snake* snake)
{
	SnakeNode* current = snake->head;
	while (current != NULL)
	{
		SetPos(current->pos.x * 2, current->pos.y);
		if (current == snake->head)
			wprintf(L"●"); // 蛇头
		else
			wprintf(L"○"); // 蛇身
		current = current->next;
	}
}

// 绘制食物
void DrawFood(Food* food)
{
	SetPos(food->pos.x * 2, food->pos.y);
	wprintf(L"★");
}

// 移动蛇
void MoveSnake(Snake* snake, Direction dir)
{
	// 创建新的头部
	SnakeNode* newHead = (SnakeNode*)malloc(sizeof(SnakeNode));
	newHead->next = snake->head;
	
	// 根据方向移动
	switch (dir)
	{
	case UP:
		newHead->pos.x = snake->head->pos.x;
		newHead->pos.y = snake->head->pos.y - 1;
		break;
	case DOWN:
		newHead->pos.x = snake->head->pos.x;
		newHead->pos.y = snake->head->pos.y + 1;
		break;
	case LEFT:
		newHead->pos.x = snake->head->pos.x - 1;
		newHead->pos.y = snake->head->pos.y;
		break;
	case RIGHT:
		newHead->pos.x = snake->head->pos.x + 1;
		newHead->pos.y = snake->head->pos.y;
		break;
	}
	
	snake->head = newHead;
	snake->direction = dir;
}

// 生成食物
void GenerateFood(Food* food, Snake* snake)
{
	bool validPosition;
	do {
		validPosition = true;
		food->pos.x = rand() % (WIDTH - 2) + 1;
		food->pos.y = rand() % (HEIGHT - 2) + 1;
		
		// 检查是否与蛇身重叠
		SnakeNode* current = snake->head;
		while (current != NULL)
		{
			if (current->pos.x == food->pos.x && current->pos.y == food->pos.y)
			{
				validPosition = false;
				break;
			}
			current = current->next;
		}
	} while (!validPosition);
	
	food->type = 1;
}

// 检查碰撞
bool CheckCollision(Snake* snake)
{
	Position head = snake->head->pos;
	
	// 检查是否撞墙
	if (head.x <= 0 || head.x >= WIDTH - 1 || head.y <= 0 || head.y >= HEIGHT - 1)
		return true;
	
	// 检查是否撞到自己
	SnakeNode* current = snake->head->next;
	while (current != NULL)
	{
		if (current->pos.x == head.x && current->pos.y == head.y)
			return true;
		current = current->next;
	}
	
	return false;
}

// 游戏循环
void GameLoop()
{
	GameState game;
	game.score = 0;
	game.speed = 200;
	game.gameOver = false;
	
	InitSnake(&game.snake);
	InitFood(&game.food);
	
	while (!game.gameOver)
	{
		// 处理输入
		if (_kbhit())
		{
			char key = _getch();
			switch (key)
			{
			case 72: // 上箭头
				if (game.snake.direction != DOWN)
					game.snake.direction = UP;
				break;
			case 80: // 下箭头
				if (game.snake.direction != UP)
					game.snake.direction = DOWN;
				break;
			case 75: // 左箭头
				if (game.snake.direction != RIGHT)
					game.snake.direction = LEFT;
				break;
			case 77: // 右箭头
				if (game.snake.direction != LEFT)
					game.snake.direction = RIGHT;
				break;
			case 61: // F3加速
				if (game.speed > 50)
					game.speed -= 20;
				break;
			case 62: // F4减速
				if (game.speed < 500)
					game.speed += 20;
				break;
			case 27: // ESC退出
				game.gameOver = true;
				break;
			}
		}
		
		// 移动蛇
		MoveSnake(&game.snake, game.snake.direction);
		
		// 检查碰撞
		if (CheckCollision(&game.snake))
		{
			game.gameOver = true;
			break;
		}
		
		// 检查是否吃到食物
		if (game.snake.head->pos.x == game.food.pos.x && 
			game.snake.head->pos.y == game.food.pos.y)
		{
			game.score += 10;
			game.snake.length++;
			GenerateFood(&game.food, &game.snake);
		}
		else
		{
			// 删除尾部
			SnakeNode* current = game.snake.head;
			while (current->next->next != NULL)
				current = current->next;
			free(current->next);
			current->next = NULL;
			game.snake.tail = current;
		}
		
		// 清屏并重绘
		system("cls");
		CreatMap();
		DrawSnake(&game.snake);
		DrawFood(&game.food);
		
		// 显示分数
		SetPos(60, 5);
		wprintf(L"分数: %d", game.score);
		SetPos(60, 7);
		wprintf(L"速度: %d", game.speed);
		
		Sleep(game.speed);
	}
	
	GameOver();
	CleanupSnake(&game.snake);
}

// 游戏结束
void GameOver()
{
	SetPos(40, 12);
	wprintf(L"游戏结束！");
	SetPos(40, 14);
	wprintf(L"按任意键退出...");
	_getch();
}

// 清理蛇的内存
void CleanupSnake(Snake* snake)
{
	SnakeNode* current = snake->head;
	while (current != NULL)
	{
		SnakeNode* next = current->next;
		free(current);
		current = next;
	}
	snake->head = snake->tail = NULL;
	snake->length = 0;
}

// 游戏开始
void GameStart()
{
	// 0.设置窗口基础属性,功能介绍

	// 设置窗口
	system("mode con cols=100 lines=30");
	system("title 贪吃蛇");

	// 隐藏控制台光标
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cursor_info;
	GetConsoleCursorInfo(handle, &cursor_info);
	cursor_info.bVisible = false;
	SetConsoleCursorInfo(handle, &cursor_info);

	// 初始化随机数种子
	srand((unsigned)time(NULL));

	// 1. 打印环境界面
	WelcomeUser();

	// 2.绘制地图
	CreatMap();

	// 3.开始游戏循环
	GameLoop();
}